local ROT = require 'rot'
local RNG = ROT.RNG

local Scene = require 'game.scene'

local SceneSpec = Scene:extend()

SceneSpec.name = 'Town'

SceneSpec.innerWidth = 50
SceneSpec.innerHeight = 50
SceneSpec.maxDepth = 4
SceneSpec.outdoors = true

function SceneSpec:build(depth, x1, y1, x2, y2)

    local floors = ROT.Type.Grid()
    local m

    if depth > 0 then
        self.name = 'Town ' .. tostring(self.depth)
        m = ROT.Map.Uniform:new(self.innerWidth, self.innerHeight, {
            roomDugPercentage = 1/12,
            roomWidth = { 2, 2 },
            roomHeight = { 2, 2 },
            snap = 4,
        })

        m:create(function (x, y, val)
            floors:setCell(x, y, val == 0 and 'dirt floor' or nil)
        end)

        local rooms = m:getRooms()
        for i = 1, #rooms do
            local r = rooms[i]
            local x1, y1, x2, y2 = r:getLeft(), r:getTop(), r:getRight(), r:getBottom()
            for x = x1, x2 do
                for y = y1, y2 do
                    self.feature:setCell(x, y, 'wood floor')
                end
            end
        end

        self:expand('wall')
        self:expand('obsidian wall')
        self:expand('dirt floor')


        for i = 1, #rooms do
            local r = rooms[i]
            local x1, y1, x2, y2 = r:getLeft(), r:getTop(), r:getRight(), r:getBottom()
            self.feature:setCell(x1 - 1, y1 - 1, 'fence')
            self.feature:setCell(x2 + 1, y1 - 1, 'fence')
            self.feature:setCell(x2 + 1, y2 + 1, 'fence')
            self.feature:setCell(x1 - 1, y2 + 1, 'fence')
        end

        for i, x, y, v in floors:each() do
            local f = self.feature:getCell(x, y)
            if f == 'obsidian wall' or f == nil then
                self.feature:setCell(x, y, v)
            end
        end

        for i = 1, #rooms do
            rooms[i]:getDoors(function(x, y)
                self.feature:setCell(x, y, 'door')
            end)
        end

        for i = 1, #rooms do
            local r = rooms[i]
            for x = r:getLeft(), r:getRight() do
                for y = r:getTop(), r:getBottom() do
                    self.feature:setCell(x, y, 'wood floor')
                end
            end
        end

        self:with('wall'):near('wood floor'):near('obsidian wall'):near('dirt floor', 0)
            :swap('floor'):apply()
        self:with('floor'):near('fence'):near('obsidian wall', 2)
            :swap('grate'):apply()
        self:with('fence'):near('wall', 0):near('door', 0):near('grate', 0)
            :swap('floor'):apply()
        self:with('fence'):near('obsidian wall', 5):near('door', 0):near('grate', 0)
            :swap('floor'):apply()

        self:with('fence'):swap('wall'):apply()
        self:with('obsidian wall'):swap('wall'):apply()
        self:with('grate'):swap('wall'):apply()
        self:with('floor'):swap('wood floor'):apply()

        self:with('wood floor'):near('wall', 7):swap('wall'):apply()
        self:with('wall'):near('dirt floor'):near('wood floor', 0):swap('rose'):apply()

        self:expand('grass')
        self:expand('tree')
    else
        local x, y = math.floor((x1 + x2) * 0.5), math.floor((y1 + y2) * 0.5)

        for _x = x1, x2 do for _y = y1, y2 do
            self.feature:setCell(_x, _y, 'tree')
        end end

        self.feature:setCell(x, y, 'grass')

        self.branches[#self.branches + 1] = { x = x, y = y, branch = 'forest' }
        self.feature:setCell(x, y, 'downstairs')
    end

    for i = 1, 3 do
        self:decimate('tree', 3, 1, 'tall grass')
        self:decimate('tree', 5, 1, 'grass')
        self:decimate('tree', 6, 1, 'tall grass')
        self:decimate('tree', 6, 1, 'grass')
    end

    if depth < 1 then
        return
    end

    local rooms = m:getRooms()
    local offset = depth == 1 and 1 or #self.previous.downstairs

    for i = 1, offset do
        local c = rooms[i]:getCenter()
        local x, y = c[1], c[2]
        self.upstairs[i] = { x = x, y = y }
        self.feature:setCell(x, y, 'upstairs')
        self.player.x, self.player.y = x, y
    end

    if depth < self.maxDepth then
        for i = offset + 1, offset + 3 do
            if not rooms[i] then break end
            local c = rooms[i]:getCenter()
            local x, y = c[1], c[2]
            self.downstairs[i - offset] = { x = x, y = y }
            self.feature:setCell(x, y, 'downstairs')
        end
    end

end

return SceneSpec
